iT邦幫忙

1

同時搞定TensorFlow、PyTorch (四):模型訓練

  • 分享至 

  • xImage
  •  
  1. 同時搞定TensorFlow、PyTorch (一):梯度下降
  2. 同時搞定TensorFlow、PyTorch (二):模型定義
  3. 同時搞定TensorFlow、PyTorch (三) :資料前置處理
  4. 同時搞定TensorFlow、PyTorch (四):模型訓練。

前言

上一篇談到TensorFlow/PyTorch資料前置處理的方式,接下來我們就各使用一支完整的範例訓練模型。

TensorFlow

  1. 載入 MNIST 資料集。
import tensorflow as tf

mnist = tf.keras.datasets.mnist

# 載入 MNIST 手寫阿拉伯數字資料
(x_train, y_train),(x_test, y_test) = mnist.load_data()

# 特徵縮放,使用常態化(Normalization),公式 = (x - min) / (max - min)
x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0

# 轉為 Dataset,含 X/Y 資料
train_ds = tf.data.Dataset.from_tensor_slices((x_train_norm, y_train))
  1. 建立模型。
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])
  1. 設定優化器(optimizer)、損失函數(loss)、效能衡量指標(metrics)。
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

損失函數使用sparse_XXX,y就不需One-hot encoding,否則須呼叫以下程式。

# 將 training 的 label 進行 one-hot encoding,例如數字 7 經過 One-hot encoding 轉換後是 0000000100,即第8個值為 1
y_train = tf.keras.utils.to_categorical(y_train) 
y_test = tf.keras.utils.to_categorical(y_test) 
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
  1. 模型訓練:只要一行程式碼。
model.fit(x_train_norm, y_train, epochs=5, validation_split=0.2)
  1. 評分(Score Model)。
score=model.evaluate(x_test_norm, y_test, verbose=0)

for i, x in enumerate(score):
    print(f'{model.metrics_names[i]}: {score[i]:.4f}')

PyTorch

  1. 載入 MNIST 資料集。
import os
import torch
from torch import nn
from torch.nn import functional as F
from torch.utils.data import DataLoader, random_split
from torchmetrics import Accuracy
from torchvision import transforms
from torchvision.datasets import MNIST

PATH_DATASETS = "" # 預設路徑
# 下載 MNIST 手寫阿拉伯數字 訓練資料
train_ds = MNIST(PATH_DATASETS, train=True, download=True, 
                 transform=transforms.ToTensor())

# 下載測試資料
test_ds = MNIST(PATH_DATASETS, train=False, download=True, 
                 transform=transforms.ToTensor())
  1. 判斷本機是否有GPU:若含NVidia顯卡,且安裝CUDA toolkits,TensorFlow會自動使用GPU進行運算及模型訓練,PyTorch則由開發者自行決定,因此,先判斷本機是否有GPU。
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
"cuda" if torch.cuda.is_available() else "cpu"
  1. 建立模型:若有GPU,to(device)指令將模型複製至GPU記憶體。
model = torch.nn.Sequential(
    torch.nn.Flatten(),
    torch.nn.Linear(28 * 28, 256), 
    torch.nn.Dropout(0.2),
    torch.nn.Linear(256, 10), 
    # 使用nn.CrossEntropyLoss()時,不需要將輸出經過softmax層,否則計算的損失會有誤
    # torch.nn.Softmax(dim=1)
).to(device)
  1. 設定優化器(optimizer)、損失函數(loss)、效能衡量指標(metrics)。
epochs = 5
lr=0.1
BATCH_SIZE = 1024  # 批量

# 建立 DataLoader
train_loader = DataLoader(train_ds, batch_size=600)

# 設定優化器(optimizer)
# optimizer = torch.optim.Adam(model.parameters(), lr=lr)
optimizer = torch.optim.Adadelta(model.parameters(), lr=lr)

criterion = nn.CrossEntropyLoss()

PyTorch不管使用何種損失函數,y是否進行One-hot encoding均可

  1. 模型訓練:要寫一大堆程式碼,包括梯度下降、計算損失/準確率等,似乎很麻煩,但是訓練過程中,可任意插入除錯訊息,例如第6行,顯示第一筆資料,不像TensorFlow必須借助Callback機制。另外,要記得把訓練資料也複製到GPU記憶體,與模型一致
model.train()
loss_list = []    
for epoch in range(1, epochs + 1):
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
#         if batch_idx == 0 and epoch == 1: print(data[0])

        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

        if batch_idx % 10 == 0:
            loss_list.append(loss.item())
            batch = batch_idx * len(data)
            data_count = len(train_loader.dataset)
            percentage = (100. * batch_idx / len(train_loader))
            print(f'Epoch {epoch}: [{batch:5d} / {data_count}] ({percentage:.0f} %)' +
                  f'  Loss: {loss.item():.6f}')
  1. 評分(Score Model):也要寫一大堆程式碼。
# 建立 DataLoader
test_loader = DataLoader(test_ds, shuffle=False, batch_size=BATCH_SIZE)

model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
    for data, target in test_loader:
        data, target = data.to(device), target.to(device)
        output = model(data)
        
        # sum up batch loss
        test_loss += criterion(output, target).item()
        
        # 預測
        pred = output.argmax(dim=1, keepdim=True)  
        
        # 正確筆數
        correct += pred.eq(target.view_as(pred)).sum().item()

# 平均損失
test_loss /= len(test_loader.dataset)
# 顯示測試結果
batch = batch_idx * len(data)
data_count = len(test_loader.dataset)
percentage = 100. * correct / data_count
print(f'平均損失: {test_loss:.4f}, 準確率: {correct}/{data_count}' + 
      f' ({percentage:.0f}%)\n')

完整程式可參閱開發者傳授 PyTorch 秘笈 的src/TF_vs_Pytorch.ipynb。

詳細流程強烈建議參考:

結論

  1. TensorFlow訓練及評分都只要一行指令,PyTorch 可以嗎? 可以試用 PyTorch Lightning 套件,首頁上附了一支簡短的程式,訓練也只要一行指令,讀者如有興趣可詳閱開發者傳授 PyTorch 秘笈
  2. PyTorch 訓練及評分步驟比較繁瑣,但是相對程序較清楚,學界會比較喜愛PyTorch,因為,可以講授得很清楚,要調整也比較容易,因此,PyTorch在研發及教育領域佔有率比TensorFlow高,反之,企業界講求效率,使用TensorFlow較多。

系列文介紹到此告一段落,希望對深度學習入門者有一絲絲的幫助。

以下為工商廣告:)。
PyTorch:
開發者傳授 PyTorch 秘笈
https://ithelp.ithome.com.tw/upload/images/20220531/20001976MhL9K2rsgO.png
預計 2022/6/20 出版。

TensorFlow:
深度學習 -- 最佳入門邁向 AI 專題實戰
https://ithelp.ithome.com.tw/upload/images/20220531/20001976ZOxC7BHyN3.jpg


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言